/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Copyright by The HDF Group.                                               *
 * Copyright by the Board of Trustees of the University of Illinois.         *
 * All rights reserved.                                                      *
 *                                                                           *
 * This file is part of HDF.  The full HDF copyright notice, including       *
 * terms governing use, modification, and redistribution, is contained in    *
 * the COPYING file, which can be found at the root of the source code       *
 * distribution tree, or in https://support.hdfgroup.org/ftp/HDF/releases/.  *
 * If you do not have access to either file, you may request a copy from     *
 * help@hdfgroup.org.                                                        *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#include "testhdf.h"

#define XSIZE    13
#define YSIZE    15
#define TESTFILE "tdf24.hdf"

#define JPEGX           46
#define JPEGY           23
#define NCOMPS          3
#define JPEGFILE        "tjpeg.hdf"
#define NONHDF_JPEGFILE "tnonhdf_jpeg.hdf"

static uint8 jpeg_8bit_orig[JPEGY][JPEGX] = {
    {200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 201, 201, 201, 200, 200, 200, 200, 200, 200, 201, 202, 204, 206, 208, 208,
     206, 202, 201, 200, 200, 204, 210, 212, 214, 212, 206, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 201, 202, 204, 203, 201, 202, 200, 199, 200, 202, 202, 203, 204,
     207, 210, 213, 218, 222, 209, 205, 207, 209, 212, 215, 220, 225, 203, 212, 216,
     218, 221, 223, 201, 201, 200, 200, 200, 200, 201, 200, 200, 201, 201},
    {200, 200, 199, 200, 200, 201, 203, 206, 207, 206, 202, 197, 193, 193, 193, 192,
     193, 199, 204, 205, 210, 219, 214, 193, 213, 225, 209, 196, 206, 222, 204, 208,
     211, 121, 127, 229, 206, 196, 198, 207, 211, 212, 214, 215, 211, 196},
    {200, 201, 200, 200, 199, 200, 200, 198, 198, 199, 202, 207, 209, 211, 195, 180,
     182, 182, 170, 111, 39,  71,  58,  64,  69,  73,  72,  82,  92,  213, 83,  73,
     126, 111, 89,  92,  209, 197, 198, 201, 81,  51,  56,  55,  210, 208},
    {54, 53, 54, 55, 53, 51, 56, 55, 50, 54, 53, 49, 54,  55, 64,  66,  63, 105, 78, 51, 59, 39, 49,
     45, 50, 66, 58, 67, 67, 71, 73, 87, 68, 80, 94, 113, 67, 202, 194, 90, 42,  39, 59, 43, 44, 58},
    {54, 52, 51, 53, 55, 56, 53, 57, 55, 57, 51,  51, 53, 50, 46, 50, 55, 51, 45,  68,  66,  63,  67,
     50, 57, 38, 47, 56, 62, 65, 65, 87, 74, 110, 59, 63, 45, 47, 98, 40, 41, 199, 199, 170, 109, 43},
    {198, 198, 200, 201, 199, 203, 202, 201, 199, 197, 197, 192, 190, 190, 191, 195,
     202, 153, 101, 197, 61,  69,  138, 182, 154, 202, 154, 73,  76,  71,  83,  83,
     150, 231, 203, 179, 49,  53,  47,  162, 208, 203, 185, 199, 203, 83},
    {199, 200, 204, 202, 202, 200, 199, 197, 195, 198, 200, 202, 207, 211, 216, 219,
     214, 199, 193, 192, 195, 195, 199, 205, 207, 218, 229, 196, 138, 121, 116, 213,
     233, 197, 207, 211, 212, 215, 216, 216, 199, 197, 199, 201, 209, 211},
    {200, 201, 201, 202, 201, 201, 201, 201, 203, 206, 206, 207, 206, 201, 202, 202,
     203, 202, 203, 205, 208, 211, 214, 221, 225, 209, 211, 213, 217, 220, 224, 225,
     200, 200, 200, 201, 207, 209, 202, 200, 201, 201, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 201, 202, 203, 201, 200, 200, 200, 200, 200, 200, 200,
     203, 209, 212, 214, 214, 211, 203, 200, 200, 200, 200, 202, 204, 202, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200}};

static uint8 jpeg_8bit_j80[JPEGY][JPEGX] = {
    {200, 200, 200, 200, 200, 200, 200, 200, 202, 202, 201, 201, 201, 200, 200, 200,
     201, 201, 200, 200, 200, 201, 202, 202, 202, 202, 201, 200, 200, 200, 200, 201,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 199, 199, 199, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 199, 199, 199, 199, 200, 200, 201, 201,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 199, 199, 199, 200, 200, 201, 201, 201,
     200, 200, 201, 201, 201, 200, 199, 199, 199, 199, 200, 201, 201, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 201, 201, 201, 201, 201, 201, 201, 201,
     201, 201, 202, 202, 202, 201, 200, 199, 202, 202, 202, 202, 202, 200, 199, 198,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 201, 201, 201, 200, 200, 200, 199, 199,
     200, 200, 200, 201, 201, 200, 200, 200, 200, 200, 201, 201, 201, 200, 200, 199,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 199, 199, 199, 198, 198, 198,
     199, 199, 198, 198, 198, 199, 200, 201, 197, 197, 197, 198, 198, 200, 201, 202,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 199, 199, 200, 200, 201, 202, 202, 203,
     201, 200, 199, 198, 199, 201, 204, 205, 203, 202, 200, 199, 198, 200, 202, 203,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 200, 201, 202, 203, 205, 207, 208, 209,
     205, 203, 201, 200, 202, 205, 208, 211, 214, 211, 206, 202, 200, 200, 201, 202,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {199, 199, 198, 199, 200, 202, 204, 205, 202, 200, 197, 198, 201, 204, 205, 205,
     220, 204, 207, 222, 225, 201, 206, 213, 205, 218, 219, 224, 222, 198, 222, 208,
     222, 208, 235, 201, 189, 204, 198, 202, 199, 201, 209, 192, 192, 217},
    {200, 200, 199, 199, 200, 201, 202, 203, 210, 208, 205, 203, 201, 197, 191, 186,
     170, 212, 216, 191, 222, 217, 218, 185, 216, 226, 200, 193, 207, 232, 193, 221,
     210, 124, 127, 218, 223, 192, 197, 207, 207, 209, 210, 220, 209, 184},
    {202, 201, 201, 200, 200, 200, 201, 201, 196, 197, 200, 203, 203, 200, 195, 191,
     196, 180, 168, 123, 34,  66,  56,  74,  57,  83,  73,  81,  94,  221, 72,  64,
     120, 119, 83,  100, 207, 190, 198, 198, 94,  44,  57,  50,  213, 215},
    {54, 54, 54, 53, 53, 54, 54, 54, 49, 51, 55, 59,  62, 63, 63,  62,  54, 110, 65, 43, 69, 40, 54,
     36, 53, 67, 57, 65, 66, 61, 94, 83, 83, 69, 102, 99, 64, 214, 195, 90, 28,  46, 63, 51, 43, 57},
    {52, 52, 53, 54, 54, 55, 55, 55, 56, 54, 51,  48, 47, 46, 48, 49,  56, 63, 48,  72,  67,  55,  51,
     65, 50, 48, 46, 70, 49, 67, 63, 86, 59, 107, 60, 73, 40, 44, 102, 36, 40, 218, 192, 165, 101, 44},
    {198, 199, 200, 201, 202, 202, 202, 202, 199, 197, 194, 190, 188, 190, 194, 198,
     196, 151, 88,  202, 61,  71,  148, 169, 165, 188, 139, 77,  86,  70,  81,  84,
     163, 226, 206, 184, 52,  46,  48,  165, 204, 189, 179, 213, 208, 79},
    {199, 200, 201, 202, 202, 201, 200, 199, 201, 203, 204, 205, 206, 209, 214, 218,
     218, 198, 195, 199, 182, 201, 202, 206, 201, 228, 240, 191, 131, 121, 110, 221,
     211, 208, 207, 198, 213, 231, 204, 220, 197, 211, 207, 194, 207, 213},
    {201, 202, 202, 203, 202, 200, 199, 197, 199, 202, 206, 206, 204, 202, 202, 203,
     205, 195, 210, 199, 211, 220, 210, 224, 224, 204, 215, 205, 227, 218, 229, 220,
     203, 201, 199, 202, 206, 206, 195, 205, 203, 194, 202, 197, 210, 190},
    {200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     203, 206, 210, 213, 213, 210, 206, 203, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     198, 199, 201, 202, 202, 201, 199, 198, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     199, 199, 198, 197, 197, 198, 199, 199, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     202, 201, 200, 199, 199, 200, 201, 202, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     199, 199, 199, 199, 199, 199, 199, 199, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     198, 199, 200, 201, 201, 200, 199, 198, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     201, 201, 202, 202, 202, 202, 201, 201, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200}};

static uint8 jpeg_8bit_j30[JPEGY][JPEGX] = {
    {199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
     199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
     199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199},
    {199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
     199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
     199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199},
    {199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
     199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
     199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199},
    {199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
     199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
     199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199},
    {199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
     199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
     199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199},
    {199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
     199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
     199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199},
    {199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
     199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
     199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199},
    {199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
     199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
     199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199},
    {202, 202, 202, 202, 202, 202, 202, 202, 196, 196, 197, 198, 200, 201, 202, 202,
     203, 206, 220, 234, 226, 203, 192, 196, 226, 219, 212, 213, 219, 222, 219, 214,
     213, 224, 225, 214, 206, 207, 207, 202, 213, 205, 195, 188, 190, 199},
    {203, 203, 203, 203, 203, 203, 203, 203, 221, 219, 214, 207, 200, 193, 188, 185,
     186, 206, 207, 186, 187, 214, 229, 222, 219, 205, 195, 203, 219, 221, 203, 183,
     192, 141, 135, 187, 212, 183, 168, 185, 208, 218, 230, 234, 226, 209},
    {203, 203, 203, 203, 203, 203, 203, 203, 207, 207, 207, 207, 207, 207, 207, 207,
     170, 194, 165, 90,  57,  75,  72,  37,  99,  84,  79,  97,  124, 132, 112, 87,
     128, 88,  84,  143, 202, 215, 201, 193, 67,  50,  51,  97,  167, 215},
    {53, 53, 53, 53, 53, 53, 53, 53, 44, 46, 49, 53, 57, 61,  64,  66,  74,  93, 87, 54, 35, 41, 36,
     17, 40, 34, 35, 49, 71, 84, 82, 75, 54, 92, 90, 63, 100, 176, 178, 120, 62, 60, 57, 54, 53, 54},
    {53, 53, 53, 53, 53, 53, 53, 53, 61, 60, 57,  53,  48, 44, 41, 40, 63, 48, 53,  73,  72,  55, 64,
     92, 76, 78, 75, 63, 51, 53, 70, 87, 71, 125, 117, 41, 10, 50, 67, 38, 38, 120, 193, 179, 97, 32},
    {203, 203, 203, 203, 203, 203, 203, 203, 199, 199, 199, 199, 199, 199, 199, 199,
     191, 141, 120, 133, 117, 79,  93,  144, 149, 151, 138, 101, 60,  46,  66,  92,
     181, 178, 176, 154, 98,  57,  82,  137, 223, 239, 247, 222, 169, 112},
    {203, 203, 203, 203, 203, 203, 203, 203, 184, 187, 192, 198, 205, 212, 217, 220,
     228, 206, 197, 206, 204, 197, 218, 253, 227, 228, 216, 186, 154, 143, 158, 178,
     233, 209, 215, 238, 214, 170, 186, 244, 203, 167, 141, 160, 208, 240},
    {202, 202, 202, 202, 202, 202, 202, 202, 209, 208, 208, 206, 205, 204, 203, 203,
     184, 203, 212, 205, 202, 209, 210, 202, 219, 220, 218, 212, 208, 212, 225, 237,
     192, 198, 200, 200, 207, 215, 209, 196, 180, 208, 233, 225, 197, 182},
    {199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
     206, 206, 206, 206, 206, 206, 206, 206, 199, 199, 199, 199, 199, 199, 199, 199,
     199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199},
    {199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
     205, 205, 205, 205, 205, 205, 205, 205, 199, 199, 199, 199, 199, 199, 199, 199,
     199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199},
    {199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
     204, 204, 204, 204, 204, 204, 204, 204, 199, 199, 199, 199, 199, 199, 199, 199,
     199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199},
    {199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
     203, 203, 203, 203, 203, 203, 203, 203, 199, 199, 199, 199, 199, 199, 199, 199,
     199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199},
    {199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
     202, 202, 202, 202, 202, 202, 202, 202, 199, 199, 199, 199, 199, 199, 199, 199,
     199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199},
    {199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
     200, 200, 200, 200, 200, 200, 200, 200, 199, 199, 199, 199, 199, 199, 199, 199,
     199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199},
    {199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
     199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
     199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199}};

static uint8 jpeg_8bit_j75[JPEGY][JPEGX] = {
    {200, 200, 200, 200, 200, 200, 200, 200, 198, 198, 198, 199, 199, 200, 200, 200,
     202, 202, 200, 199, 199, 199, 199, 200, 199, 199, 200, 201, 201, 201, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 199, 199, 200, 200, 200, 200, 200, 200,
     202, 202, 201, 201, 200, 200, 200, 200, 201, 201, 202, 202, 201, 201, 200, 199,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 201, 201, 200, 200, 200, 200, 200, 200,
     201, 202, 202, 202, 202, 201, 200, 200, 203, 203, 202, 202, 201, 200, 200, 199,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 199, 199, 199, 199,
     199, 200, 201, 202, 202, 201, 200, 199, 201, 201, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 199, 199, 199, 198, 198, 198, 198, 198,
     198, 199, 199, 200, 200, 200, 199, 199, 199, 199, 198, 198, 199, 200, 201, 202,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 198, 198, 198, 199, 199, 200, 200, 200,
     200, 200, 199, 199, 199, 200, 201, 202, 201, 200, 199, 198, 198, 200, 201, 203,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 198, 199, 199, 201, 202, 203, 204, 204,
     204, 202, 200, 199, 200, 202, 204, 206, 207, 205, 203, 200, 199, 200, 201, 202,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 199, 200, 201, 202, 204, 206, 207, 207,
     207, 205, 202, 200, 200, 203, 207, 210, 213, 210, 207, 203, 201, 200, 200, 201,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {202, 201, 200, 199, 200, 201, 203, 204, 202, 199, 196, 196, 200, 203, 203, 202,
     205, 222, 189, 234, 214, 209, 216, 203, 204, 212, 224, 210, 226, 204, 214, 215,
     219, 218, 214, 203, 200, 207, 189, 209, 194, 211, 188, 199, 211, 185},
    {202, 201, 200, 200, 200, 202, 203, 204, 212, 208, 204, 201, 199, 195, 190, 186,
     186, 215, 205, 196, 218, 218, 206, 197, 223, 224, 188, 217, 204, 225, 195, 205,
     211, 118, 158, 234, 196, 204, 194, 209, 208, 210, 216, 224, 211, 194},
    {198, 198, 198, 197, 198, 199, 200, 200, 199, 199, 200, 202, 204, 203, 200, 197,
     176, 184, 165, 126, 21,  66,  63,  65,  66,  68,  78,  78,  89,  200, 87,  66,
     117, 120, 65,  94,  212, 196, 206, 197, 80,  49,  56,  45,  206, 205},
    {54, 54, 54, 54, 55, 55, 56, 56, 49, 50, 53, 57, 60,  62, 62,  62,  63, 91, 80, 31, 78, 53, 41,
     53, 63, 64, 48, 65, 75, 79, 80, 89, 83, 90, 90, 109, 76, 202, 178, 94, 41, 52, 47, 58, 50, 65},
    {54, 54, 55, 55, 56, 56, 56, 56, 59, 57, 55,  51, 48, 46, 46, 46, 62, 67, 49,  72,  82,  42,  55,
     61, 42, 30, 65, 48, 66, 64, 53, 82, 53, 115, 63, 58, 46, 52, 86, 43, 34, 200, 200, 149, 103, 61},
    {197, 197, 198, 199, 200, 199, 199, 199, 197, 197, 196, 194, 192, 193, 196, 199,
     187, 139, 105, 206, 44,  86,  158, 165, 167, 210, 135, 91,  55,  64,  104, 85,
     172, 219, 206, 182, 36,  55,  59,  163, 211, 188, 208, 207, 212, 63},
    {199, 200, 201, 203, 203, 203, 202, 201, 192, 196, 200, 203, 205, 209, 214, 218,
     237, 203, 178, 202, 187, 178, 206, 212, 202, 216, 224, 204, 133, 129, 121, 199,
     221, 204, 209, 216, 207, 206, 228, 202, 183, 218, 188, 176, 208, 219},
    {198, 199, 201, 202, 203, 202, 201, 200, 202, 205, 209, 208, 204, 201, 201, 202,
     198, 195, 207, 203, 219, 218, 210, 215, 226, 210, 214, 214, 211, 226, 201, 238,
     208, 188, 212, 192, 209, 217, 199, 201, 209, 192, 207, 206, 207, 195},
    {200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     202, 206, 211, 215, 215, 211, 206, 202, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     198, 199, 201, 203, 203, 201, 199, 198, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     201, 200, 199, 198, 198, 199, 200, 201, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     203, 202, 201, 199, 199, 201, 202, 203, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     198, 198, 198, 199, 199, 198, 198, 198, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     197, 198, 199, 200, 200, 199, 198, 197, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200},
    {200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
     201, 201, 202, 202, 202, 202, 201, 201, 200, 200, 200, 200, 200, 200, 200, 200,
     200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200}};

static uint8 jpeg_24bit_orig[JPEGY * JPEGX * 3] = {
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 99,  0,   255, 99,  0,   255, 99,  0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 99,  0,   255, 95,  0,   255, 87,  0,   255, 79,  0,
    255, 71,  0,   255, 71,  0,   255, 79,  0,   255, 95,  0,   255, 99,  0,   255, 103, 0,   255, 103, 0,
    255, 87,  0,   255, 63,  0,   255, 55,  0,   255, 47,  0,   255, 55,  0,   255, 79,  0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 99,  0,   255, 95,  0,   255, 87,  0,   255, 91,  0,   255, 99,  0,   255, 95,  0,   255, 103, 0,
    255, 107, 0,   255, 103, 0,   255, 95,  0,   255, 95,  0,   255, 91,  0,   255, 87,  0,   255, 75,  0,
    255, 63,  0,   255, 51,  0,   255, 31,  0,   255, 15,  0,   255, 67,  0,   255, 83,  0,   255, 75,  0,
    255, 67,  0,   255, 55,  0,   255, 43,  0,   255, 23,  0,   255, 3,   0,   255, 91,  0,   255, 55,  0,
    255, 39,  0,   255, 31,  0,   255, 19,  0,   255, 11,  0,   255, 99,  0,   255, 99,  0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 99,  0,   255, 103, 0,   255, 103, 0,   255, 99,  0,
    255, 99,  0,   255, 103, 0,   255, 103, 0,   255, 107, 0,   255, 103, 0,   255, 103, 0,   255, 99,  0,
    255, 91,  0,   255, 79,  0,   255, 75,  0,   255, 79,  0,   255, 95,  0,   255, 115, 0,   255, 131, 0,
    255, 131, 0,   255, 131, 0,   255, 135, 0,   255, 131, 0,   255, 107, 0,   255, 87,  0,   255, 83,  0,
    255, 63,  0,   255, 27,  0,   255, 47,  0,   255, 131, 0,   255, 51,  0,   255, 3,   0,   255, 67,  0,
    255, 119, 0,   255, 79,  0,   255, 15,  0,   255, 87,  0,   255, 71,  0,   255, 59,  0,   91,  255, 163,
    115, 255, 139, 241, 0,   0,   255, 79,  0,   255, 119, 0,   255, 111, 0,   255, 75,  0,   255, 59,  0,
    255, 55,  0,   255, 47,  0,   255, 43,  0,   255, 59,  0,   255, 119, 0,   255, 103, 0,   255, 99,  0,
    255, 103, 0,   255, 103, 0,   255, 107, 0,   255, 103, 0,   255, 103, 0,   255, 111, 0,   255, 111, 0,
    255, 107, 0,   255, 95,  0,   255, 75,  0,   255, 67,  0,   255, 59,  0,   255, 123, 0,   255, 183, 0,
    255, 175, 0,   255, 175, 0,   255, 223, 0,   51,  255, 203, 0,   23,  255, 0,   151, 255, 0,   99,  255,
    0,   123, 255, 0,   143, 255, 0,   159, 255, 0,   155, 255, 0,   195, 255, 0,   235, 255, 255, 51,  0,
    0,   199, 255, 0,   159, 255, 111, 255, 143, 51,  255, 203, 0,   223, 255, 0,   235, 255, 255, 67,  0,
    255, 115, 0,   255, 111, 0,   255, 99,  0,   0,   191, 255, 0,   71,  255, 0,   91,  255, 0,   87,  255,
    255, 63,  0,   255, 71,  0,   0,   83,  255, 0,   79,  255, 0,   83,  255, 0,   87,  255, 0,   79,  255,
    0,   71,  255, 0,   91,  255, 0,   87,  255, 0,   67,  255, 0,   83,  255, 0,   79,  255, 0,   63,  255,
    0,   83,  255, 0,   87,  255, 0,   123, 255, 0,   131, 255, 0,   119, 255, 27,  255, 227, 0,   179, 255,
    0,   71,  255, 0,   103, 255, 0,   23,  255, 0,   63,  255, 0,   47,  255, 0,   67,  255, 0,   131, 255,
    0,   99,  255, 0,   135, 255, 0,   135, 255, 0,   151, 255, 0,   159, 255, 0,   215, 255, 0,   139, 255,
    0,   187, 255, 0,   243, 255, 59,  255, 195, 0,   135, 255, 255, 95,  0,   255, 127, 0,   0,   227, 255,
    0,   35,  255, 0,   23,  255, 0,   103, 255, 0,   39,  255, 0,   43,  255, 0,   99,  255, 0,   83,  255,
    0,   75,  255, 0,   71,  255, 0,   79,  255, 0,   87,  255, 0,   91,  255, 0,   79,  255, 0,   95,  255,
    0,   87,  255, 0,   95,  255, 0,   71,  255, 0,   71,  255, 0,   79,  255, 0,   67,  255, 0,   51,  255,
    0,   67,  255, 0,   87,  255, 0,   71,  255, 0,   47,  255, 0,   139, 255, 0,   131, 255, 0,   119, 255,
    0,   135, 255, 0,   67,  255, 0,   95,  255, 0,   19,  255, 0,   55,  255, 0,   91,  255, 0,   115, 255,
    0,   127, 255, 0,   127, 255, 0,   215, 255, 0,   163, 255, 47,  255, 207, 0,   103, 255, 0,   119, 255,
    0,   47,  255, 0,   55,  255, 0,   255, 255, 0,   27,  255, 0,   31,  255, 255, 107, 0,   255, 107, 0,
    255, 223, 0,   43,  255, 211, 0,   39,  255, 255, 111, 0,   255, 111, 0,   255, 103, 0,   255, 99,  0,
    255, 107, 0,   255, 91,  0,   255, 95,  0,   255, 99,  0,   255, 107, 0,   255, 115, 0,   255, 115, 0,
    255, 135, 0,   255, 143, 0,   255, 143, 0,   255, 139, 0,   255, 123, 0,   255, 95,  0,   219, 255, 35,
    11,  255, 243, 255, 115, 0,   0,   111, 255, 0,   143, 255, 159, 255, 95,  255, 175, 0,   223, 255, 31,
    255, 95,  0,   223, 255, 31,  0,   159, 255, 0,   171, 255, 0,   151, 255, 0,   199, 255, 0,   199, 255,
    207, 255, 47,  233, 0,   0,   255, 91,  0,   255, 187, 0,   0,   63,  255, 0,   79,  255, 0,   55,  255,
    255, 255, 0,   255, 71,  0,   255, 91,  0,   255, 163, 0,   255, 107, 0,   255, 91,  0,   0,   199, 255,
    255, 107, 0,   255, 103, 0,   255, 87,  0,   255, 95,  0,   255, 95,  0,   255, 103, 0,   255, 107, 0,
    255, 115, 0,   255, 123, 0,   255, 111, 0,   255, 103, 0,   255, 95,  0,   255, 75,  0,   255, 59,  0,
    255, 39,  0,   255, 27,  0,   255, 47,  0,   255, 107, 0,   255, 131, 0,   255, 135, 0,   255, 123, 0,
    255, 123, 0,   255, 107, 0,   255, 83,  0,   255, 75,  0,   255, 31,  0,   241, 0,   0,   255, 119, 0,
    159, 255, 95,  91,  255, 163, 71,  255, 183, 255, 51,  0,   224, 0,   0,   255, 115, 0,   255, 75,  0,
    255, 59,  0,   255, 55,  0,   255, 43,  0,   255, 39,  0,   255, 39,  0,   255, 107, 0,   255, 115, 0,
    255, 107, 0,   255, 99,  0,   255, 67,  0,   255, 59,  0,   255, 103, 0,   255, 99,  0,   255, 99,  0,
    255, 95,  0,   255, 99,  0,   255, 99,  0,   255, 99,  0,   255, 99,  0,   255, 91,  0,   255, 79,  0,
    255, 79,  0,   255, 75,  0,   255, 79,  0,   255, 99,  0,   255, 95,  0,   255, 95,  0,   255, 91,  0,
    255, 95,  0,   255, 91,  0,   255, 83,  0,   255, 71,  0,   255, 59,  0,   255, 47,  0,   255, 19,  0,
    255, 3,   0,   255, 67,  0,   255, 59,  0,   255, 51,  0,   255, 35,  0,   255, 23,  0,   255, 7,   0,
    255, 3,   0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 99,  0,   255, 75,  0,   255, 67,  0,
    255, 95,  0,   255, 103, 0,   255, 99,  0,   255, 99,  0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 99,  0,
    255, 95,  0,   255, 91,  0,   255, 99,  0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 91,  0,   255, 67,  0,   255, 55,  0,   255, 47,  0,
    255, 47,  0,   255, 59,  0,   255, 91,  0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 95,  0,   255, 87,  0,   255, 95,  0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,   255, 103, 0,
    255, 103, 0};

void test_GRgetcomptype(void); /* in "tdfr8.c" */

static void check_im_pal(int32 oldx, int32 oldy, int32 newx, int32 newy, uint8 *oldim, uint8 *newim,
                         uint8 *oldpal, uint8 *newpal);

/* These two functions are in tusejpegfuncs.c.  They use JPEG functions directly
   to compress and decompress the same data as in test_r24_jpeg, to verify that
   the DFR24 API work correctly regardless which JPEG library is used */
int  comp_using_jpeglib(const char *filename, long *file_offset, int im_height, int im_width, int im_ncomps,
                        int quality, uint8 *written_buffer);
int  decomp_using_jpeglib(const char *filename, long file_offset, int im_height, int im_width, int im_ncomps,
                          uint8 *read_buffer);
void test_r24_jpeg(void);

/* ------------------------------- test_r24 ------------------------------- */

void
test_r24(void)
{
    int32  xd, yd;
    int    il;
    int    Error;
    char   buf[YSIZE][XSIZE][3];
    char   buf1[YSIZE][3][XSIZE];
    char   buf2[3][YSIZE][XSIZE];
    char   in[YSIZE][XSIZE][3];
    char   in1[YSIZE][3][XSIZE];
    char   in2[3][YSIZE][XSIZE];
    int    i, j, ret;
    uint16 ref0, ref1, ref2;
    uint8 *jpeg_24bit_temp;

    jpeg_24bit_temp = (uint8 *)malloc(JPEGX * JPEGY * 3);
    if (!jpeg_24bit_temp) {
        fprintf(stderr, "Out of memory!\n");
        exit(1);
    }

    for (i = 0; i < YSIZE; i++)
        for (j = 0; j < XSIZE; j++) {
            buf[i][j][0] = buf[i][j][1] = buf[i][j][2] = (char)(i + j);
            buf1[i][0][j] = buf1[i][1][j] = buf1[i][2][j] = (char)(i | j);
            buf2[0][i][j] = buf2[1][i][j] = buf2[2][i][j] = (char)(i ^ j);
        }

    MESSAGE(5, printf("Writing 24bit images with differing interlacing\n"););

    ret = DF24setil(DFIL_PIXEL);
    RESULT("DF24setil");
    ret = DF24putimage(TESTFILE, &(buf[0][0][0]), XSIZE, YSIZE);
    RESULT("DF24putimage");
    ref0 = DF24lastref();

    ret = DF24setil(DFIL_LINE);
    RESULT("DF24setil");
    ret = DF24addimage(TESTFILE, &(buf1[0][0][0]), XSIZE, YSIZE);
    RESULT("DF24addimage");
    ref1 = DF24lastref();

    ret = DF24setil(DFIL_PLANE);
    RESULT("DF24setil");
    ret = DF24addimage(TESTFILE, &(buf2[0][0][0]), XSIZE, YSIZE);
    RESULT("DF24addimage");
    ref2 = DF24lastref();

    if ((ret = DF24nimages(TESTFILE)) != 3) {
        fprintf(stderr, "  >>> DF24nimages() gives wrong number: %d <<<\n", ret);
        num_errs++;
    }

    /* read image 0 */

    MESSAGE(5, printf("Reading and verifying 24bit images\n"););

    ret = DF24restart();
    RESULT("DF24restart");
    ret = DF24reqil(DFIL_PIXEL);
    RESULT("DF24reqil");
    ret = DF24getdims(TESTFILE, &xd, &yd, &il);
    RESULT("DF24getdims");
    if (ret == FAIL)
        HEprint(stderr, 0);

    if ((xd != XSIZE) || (yd != YSIZE) || il != 0) {
        fprintf(stderr, "Returned meta-data is wrong for image 0\n");
        num_errs++;
    }

    ret = DF24getimage(TESTFILE, in, XSIZE, YSIZE);
    RESULT("DF24getimage");
    Error = FALSE;
    for (i = 0; i < YSIZE; i++)
        for (j = 0; j < XSIZE; j++)
            if (in[i][j][0] != buf[i][j][0] || in[i][j][1] != buf[i][j][1] || in[i][j][2] != buf[i][j][2]) {
                Error = TRUE;
            }

    if (Error) {
        printf("in:\n");
        for (i = 0; i < YSIZE; i++) {
            for (j = 0; j < XSIZE; j++)
                printf("(%d,%d,%d)", (int)in[i][j][0], (int)in[i][j][1], (int)in[i][j][2]);
            printf("\n");
        }
        printf("buf:\n");
        for (i = 0; i < YSIZE; i++) {
            for (j = 0; j < XSIZE; j++)
                printf("(%d,%d,%d)", (int)buf[i][j][0], (int)buf[i][j][1], (int)buf[i][j][2]);
            printf("\n");
        }
        fprintf(stderr, "Image 0 was incorrect\n");
        num_errs++;
    }

    if (ref0 != DF24lastref()) {
        fprintf(stderr, "Bogus lastref for image 0\n");
        num_errs++;
    }

    /* read image 1 */

    ret = DF24getdims(TESTFILE, &xd, &yd, &il);
    RESULT("DF24getdims");

    if ((xd != XSIZE) || (yd != YSIZE) || il != 1) {
        fprintf(stderr, "Returned meta-data is wrong for image 1\n");
        num_errs++;
    }

    ret = DF24getimage(TESTFILE, in, XSIZE, YSIZE);
    RESULT("DF24getimage");
    Error = FALSE;
    for (i = 0; i < YSIZE; i++)
        for (j = 0; j < XSIZE; j++)
            if (in[i][j][0] != buf1[i][0][j] || in[i][j][1] != buf1[i][1][j] ||
                in[i][j][2] != buf1[i][2][j]) {
                Error = TRUE;
            }

    if (Error) {
        fprintf(stderr, "Image 1 was incorrect\n");
        num_errs++;
    }

    if (ref1 != DF24lastref()) {
        fprintf(stderr, "Bogus lastref for image 1\n");
        num_errs++;
    }

    /* read image 2 */

    ret = DF24getdims(TESTFILE, &xd, &yd, &il);
    RESULT("DF24getdims");

    if ((xd != XSIZE) || (yd != YSIZE) || il != 2) {
        fprintf(stderr, "Returned meta-data is wrong for image 2\n");
        num_errs++;
    }

    ret = DF24getimage(TESTFILE, in, XSIZE, YSIZE);
    RESULT("DF24getimage");
    Error = FALSE;
    for (i = 0; i < YSIZE; i++)
        for (j = 0; j < XSIZE; j++)
            if (in[i][j][0] != buf2[0][i][j] || in[i][j][1] != buf2[1][i][j] ||
                in[i][j][2] != buf2[2][i][j]) {
                Error = TRUE;
            }

    if (Error) {
        fprintf(stderr, "Image 2 was incorrect\n");
        num_errs++;
    }

    if (ref2 != DF24lastref()) {
        fprintf(stderr, "Bogus lastref for image 2\n");
        num_errs++;
    }

    ret = DF24restart();
    RESULT("DF24restart");

    /* read image 3 */

    ret = DF24reqil(DFIL_LINE);
    RESULT("DF24reqil");
    ret = DF24getdims(TESTFILE, &xd, &yd, &il);
    RESULT("DF24getdims");

    if ((xd != XSIZE) || (yd != YSIZE) || il != 0) {
        fprintf(stderr, "Returned meta-data is wrong for image 3\n");
        num_errs++;
    }

    ret = DF24getimage(TESTFILE, in1, XSIZE, YSIZE);
    RESULT("DF24getimage");
    Error = FALSE;
    for (i = 0; i < YSIZE; i++)
        for (j = 0; j < XSIZE; j++)
            if (in1[i][0][j] != buf[i][j][0] || in1[i][1][j] != buf[i][j][1] ||
                in1[i][2][j] != buf[i][j][2]) {
                Error = TRUE;
            }

    if (Error) {
        fprintf(stderr, "Image 3 was incorrect\n");
        num_errs++;
    }

    /* read image 4 */

    ret = DF24getdims(TESTFILE, &xd, &yd, &il);
    RESULT("DF24getdims");

    if ((xd != XSIZE) || (yd != YSIZE) || il != 1) {
        fprintf(stderr, "Returned meta-data is wrong for image 4\n");
        num_errs++;
    }

    ret = DF24getimage(TESTFILE, in1, XSIZE, YSIZE);
    RESULT("DF24getimage");
    Error = FALSE;
    for (i = 0; i < YSIZE; i++)
        for (j = 0; j < XSIZE; j++)
            if (in1[i][0][j] != buf1[i][0][j] || in1[i][1][j] != buf1[i][1][j] ||
                in1[i][2][j] != buf1[i][2][j]) {
                Error = TRUE;
            }

    if (Error) {
        fprintf(stderr, "Image 4 was incorrect\n");
        num_errs++;
    }

    /* read image 5 */

    ret = DF24getdims(TESTFILE, &xd, &yd, &il);
    RESULT("DF24getdims");

    if ((xd != XSIZE) || (yd != YSIZE) || il != 2) {
        fprintf(stderr, "Returned meta-data is wrong for image 5\n");
        num_errs++;
    }

    ret = DF24getimage(TESTFILE, in1, XSIZE, YSIZE);
    RESULT("DF24getimage");
    Error = FALSE;
    for (i = 0; i < YSIZE; i++)
        for (j = 0; j < XSIZE; j++)
            if (in1[i][0][j] != buf2[0][i][j] || in1[i][1][j] != buf2[1][i][j] ||
                in1[i][2][j] != buf2[2][i][j]) {
                Error = TRUE;
            }

    if (Error) {
        fprintf(stderr, "Image 5 was incorrect\n");
        num_errs++;
    }

    /* read image 6 */

    ret = DF24restart();
    RESULT("DF24restart");

    ret = DF24reqil(DFIL_PLANE);
    RESULT("DF24reqil");

    ret = DF24getdims(TESTFILE, &xd, &yd, &il);
    RESULT("DF24getdims");

    if ((xd != XSIZE) || (yd != YSIZE) || il != 0) {
        fprintf(stderr, "Returned meta-data is wrong for image 6\n");
        num_errs++;
    }

    ret = DF24getimage(TESTFILE, in2, XSIZE, YSIZE);
    RESULT("DF24getimage");
    Error = FALSE;
    for (i = 0; i < YSIZE; i++)
        for (j = 0; j < XSIZE; j++)
            if (in2[0][i][j] != buf[i][j][0] || in2[1][i][j] != buf[i][j][1] ||
                in2[2][i][j] != buf[i][j][2]) {
                Error = TRUE;
            }

    if (Error) {
        fprintf(stderr, "Image 6 was incorrect\n");
        num_errs++;
    }

    /* read image 7 */
    ret = DF24getdims(TESTFILE, &xd, &yd, &il);
    RESULT("DF24getdims");

    if ((xd != XSIZE) || (yd != YSIZE) || il != 1) {
        fprintf(stderr, "Returned meta-data is wrong for image 7\n");
        num_errs++;
    }

    ret = DF24getimage(TESTFILE, in2, XSIZE, YSIZE);
    RESULT("DF24getimage");
    for (i = 0; i < YSIZE; i++)
        for (j = 0; j < XSIZE; j++)
            if (in2[0][i][j] != buf1[i][0][j] || in2[1][i][j] != buf1[i][1][j] ||
                in2[2][i][j] != buf1[i][2][j]) {
                Error = TRUE;
            }

    if (Error) {
        fprintf(stderr, "Image 7 was incorrect\n");
        num_errs++;
    }

    /* read image 8 */

    ret = DF24getdims(TESTFILE, &xd, &yd, &il);
    RESULT("DF24getdims");

    if ((xd != XSIZE) || (yd != YSIZE) || il != 2) {
        fprintf(stderr, "Returned meta-data is wrong for image 8\n");
        num_errs++;
    }

    ret = DF24getimage(TESTFILE, in2, XSIZE, YSIZE);
    RESULT("DF24getimage");
    Error = FALSE;
    for (i = 0; i < YSIZE; i++)
        for (j = 0; j < XSIZE; j++)
            if (in2[0][i][j] != buf2[0][i][j] || in2[1][i][j] != buf2[1][i][j] ||
                in2[2][i][j] != buf2[2][i][j]) {
                Error = TRUE;
            }

    if (Error) {
        fprintf(stderr, "Image 8 was incorrect\n");
        num_errs++;
    }

    free(jpeg_24bit_temp);

    /* Test 24-bit images with JPEG compression */
    test_r24_jpeg();
}

/**********************************************************************
 Utility function: read_binary_block
 Description:
        read_binary_block opens the given file in binary mode, seeks
        to the specified offset, then reads into the provided buffer
        nitems of values.
***********************************************************************/
size_t
read_binary_block(const char *filename, /* file to be read */
                  int32       offset,   /* position to start reading from */
                  size_t      nitems,   /* number of bytes to read */
                  uint8      *buffer)        /* buffer to store the binary data in */
{
    FILE  *fd;
    size_t readlen = 0; /* number of bytes actually read */

    /* Open the file to read binary data */
    if ((fd = fopen(filename, "rb")) == NULL) {
        fprintf(stderr, "can't open %s\n", filename);
        exit(1);
    }

    /* Forward to the specified offset to start reading */
    if (fseek(fd, (off_t)offset, SEEK_SET) == -1) {
        fprintf(stderr, "can't seek offset %d\n", (int)offset);
        exit(1);
    }

    /* Read in the specified block of data */
    readlen = fread((void *)buffer, 1, nitems, fd);

    fclose(fd);

    return readlen;
}

/* ------------------------------- test_r24_jpeg ------------------------------- */

#define N_IMAGES 3
void
test_r24_jpeg(void)
{
    int32 fid, grid,            /* file ID and GR interface ID */
        riid;                   /* raster image ID */
    comp_info cinfo;            /* compression information for the JPEG */
    int32     xd, yd;           /* image's dimensions */
    int       il;               /* image's interlace */
    long      begin_offset = 0, /* offset at the beginning of image's data */
        end_offset         = 0; /* offset at the end of image's data */
    uint8 *jpeg_24bit_temp;     /* buffer for 24-bit image data */
    uint8  jpeglib_readbuf[JPEGY * JPEGX * NCOMPS];
    /* buffer for data read by JPEG function */
    int32  offset, length;     /* offset/length in the HDF file */
    int32  nonhdf_offset;      /* offset in the nonHDF file */
    int    status;             /* status returned from GR routines */
    int    ii;                 /* indices */
    int32  n_images, n_fattrs; /* number of images and number of file attrs */
    uint8 *hdf_buffer,         /* buffer of data read from HDF file */
        *nonhdf_buffer;        /* buffer of data read from non-HDF file */
    int ret;

    /* Allocate buffer for DF24getimage to store read data */
    jpeg_24bit_temp = (uint8 *)malloc(JPEGX * JPEGY * 3);
    if (!jpeg_24bit_temp) {
        fprintf(stderr, "Out of memory!\n");
        exit(1);
    }

    MESSAGE(5, printf("\nStoring 24-bit images with JPEG compression\n"););

    ret = DF24setil(DFIL_PIXEL);
    RESULT("DF24setil");

    MESSAGE(6, printf("Storing first image with JPEG quality 80\n"););
    cinfo.jpeg.quality        = 80;
    cinfo.jpeg.force_baseline = TRUE;
    DF24setcompress(COMP_JPEG, &cinfo);
    ret = DF24putimage((const char *)JPEGFILE, jpeg_24bit_orig, JPEGX, JPEGY);
    RESULT("DF24putimage");

    MESSAGE(6, printf("Storing second image with JPEG quality 30\n"););
    cinfo.jpeg.quality        = 30;
    cinfo.jpeg.force_baseline = TRUE;
    DF24setcompress(COMP_JPEG, &cinfo);
    ret = DF24addimage((const char *)JPEGFILE, jpeg_24bit_orig, JPEGX, JPEGY);
    RESULT("DF24addimage");

    MESSAGE(6, printf("Storing third image with JPEG default quality of 75\n"););
    cinfo.jpeg.quality        = 75;
    cinfo.jpeg.force_baseline = TRUE;
    DF24setcompress(COMP_JPEG, &cinfo);
    ret = DF24addimage((const char *)JPEGFILE, jpeg_24bit_orig, JPEGX, JPEGY);
    RESULT("DF24addimage");

    if (DF24nimages(JPEGFILE) != 3) {
        fprintf(stderr, "  >>> DF24nimages() gives wrong number for JPEG images<<<\n");
        num_errs++;
    }

    MESSAGE(5, printf("\nReading and verifying 24bit JPEG'ed images\n\n"););

    ret = DF24restart();
    RESULT("DF24restart");

    ret = DF24reqil(DFIL_PIXEL);
    RESULT("DF24reqil");

    /* Get dimensions of first image */
    ret = DF24getdims(JPEGFILE, &xd, &yd, &il);
    RESULT("DF24getdims");

    if ((xd != JPEGX) || (yd != JPEGY)) {
        fprintf(stderr, "Returned meta-data is wrong for JPEG quality 80 image\n");
        fprintf(stderr, "xd=%d, yd=%d\n", (int)xd, (int)yd);
        num_errs++;
    }

    ret = DF24getimage(JPEGFILE, jpeg_24bit_temp, JPEGX, JPEGY);
    RESULT("DF24getimage");

    /* Compress the same data using the JPEG library directly, with quality 80 */
    comp_using_jpeglib(NONHDF_JPEGFILE, &end_offset, JPEGY, JPEGX, NCOMPS, 80, jpeg_24bit_orig);

    /* Read back the data using JPEG library directly */
    decomp_using_jpeglib(NONHDF_JPEGFILE, begin_offset, JPEGY, JPEGX, NCOMPS, jpeglib_readbuf);

    /* Compare data decompressed by HDF against that by JPEG lib, the buffers
       should be identical */
    if (memcmp(jpeg_24bit_temp, jpeglib_readbuf, JPEGY * JPEGX * NCOMPS)) {
        fprintf(stderr, "24-bit JPEG quality 80 image was incorrect\n");
        print_mismatched(jpeg_24bit_temp, jpeglib_readbuf, JPEGY * JPEGX * NCOMPS);
        num_errs++;
    }

    /* Get dimensions of second image */
    ret = DF24getdims(JPEGFILE, &xd, &yd, &il);
    RESULT("DF24getdims");

    if ((xd != JPEGX) || (yd != JPEGY)) {
        fprintf(stderr, "Returned meta-data is wrong for JPEG quality 30 image\n");
        fprintf(stderr, "xd=%d, yd=%d\n", (int)xd, (int)yd);
        num_errs++;
    }

    ret = DF24getimage(JPEGFILE, jpeg_24bit_temp, JPEGX, JPEGY);
    RESULT("DF24getimage");

    begin_offset = end_offset;

    /* Compress the same data using the JPEG library directly, with quality 30 */
    comp_using_jpeglib(NONHDF_JPEGFILE, &end_offset, JPEGY, JPEGX, NCOMPS, 30, jpeg_24bit_orig);

    /* Read back the data using JPEG library directly */
    decomp_using_jpeglib(NONHDF_JPEGFILE, begin_offset, JPEGY, JPEGX, NCOMPS, jpeglib_readbuf);

    /* Compare data decompressed by HDF against that by JPEG lib, the buffers
       should be identical */
    if (memcmp(jpeg_24bit_temp, jpeglib_readbuf, JPEGY * JPEGX * NCOMPS)) {
        fprintf(stderr, "24-bit JPEG quality 30 image was incorrect\n");
        print_mismatched(jpeg_24bit_temp, jpeglib_readbuf, JPEGY * JPEGX * NCOMPS);
        num_errs++;
    }

    /* Get dimensions of third image */
    ret = DF24getdims(JPEGFILE, &xd, &yd, &il);
    RESULT("DF24getdims");

    if ((xd != JPEGX) || (yd != JPEGY)) {
        fprintf(stderr, "Returned meta-data is wrong for JPEG quality 75 image\n");
        fprintf(stderr, "xd=%d, yd=%d\n", (int)xd, (int)yd);
        num_errs++;
    }

    ret = DF24getimage(JPEGFILE, jpeg_24bit_temp, JPEGX, JPEGY);
    RESULT("DF24getimage");

    begin_offset = end_offset;

    /* Compress the same data using the JPEG library directly, with quality 75 */
    comp_using_jpeglib(NONHDF_JPEGFILE, &end_offset, JPEGY, JPEGX, NCOMPS, 75, jpeg_24bit_orig);

    /* Read back the data using JPEG library directly */
    decomp_using_jpeglib(NONHDF_JPEGFILE, begin_offset, JPEGY, JPEGX, NCOMPS, jpeglib_readbuf);

    /* Compare data decompressed by HDF against that by JPEG lib, the buffers
       should be identical */
    if (memcmp(jpeg_24bit_temp, jpeglib_readbuf, JPEGY * JPEGX * NCOMPS)) {
        fprintf(stderr, "24-bit JPEG quality 75 image was incorrect\n");
        print_mismatched(jpeg_24bit_temp, jpeglib_readbuf, JPEGY * JPEGX * NCOMPS);
        num_errs++;
    }

    free(jpeg_24bit_temp);

    /********************************************************************
      Verify raw data in HDF and NON-HDF files using offsets and lengths.
    ********************************************************************/

    /* Re-open the file with GR interface */
    fid = Hopen(JPEGFILE, DFACC_RDONLY, 0);
    CHECK_VOID(fid, FAIL, "Hopen");
    grid = GRstart(fid);
    CHECK_VOID(grid, FAIL, "GRstart");

    /* Get the number of images in the file */
    status = GRfileinfo(grid, &n_images, &n_fattrs);
    CHECK_VOID(status, FAIL, "GRfileinfo");
    VERIFY_VOID(n_images, N_IMAGES, "GRfileinfo");

    /* Open each image and get its data information.  Read the block of
       binary data from the HDF file and the non-HDF file.  Then, verify
       that the two buffers are identical.  Note that the non-HDF file only
       contains the image data, thus the offset will start at 0. */
    nonhdf_offset = 0;
    for (ii = 0; ii < n_images; ii++) {
        size_t read_len = 0;

        /* Get access to each image */
        riid = GRselect(grid, ii);
        CHECK_VOID(riid, FAIL, "GRselect");

        /* Get the image's data information */
        status = GRgetdatainfo(riid, 0, 1, &offset, &length);
        CHECK_VOID(status, FAIL, "GRgetdatainfo");

        /* Allocate buffers for the data from the HDF file and non-HDF file */
        hdf_buffer = (uint8 *)malloc((size_t)length * sizeof(uint8));
        CHECK_ALLOC(hdf_buffer, "hdf_buffer", "test_r24_jpeg");
        nonhdf_buffer = (uint8 *)malloc((size_t)length * sizeof(uint8));
        CHECK_ALLOC(nonhdf_buffer, "nonhdf_buffer", "test_r24_jpeg");

        /* Read the block of data from the HDF file using offset/length returned by
           GRgetdatainfo and verify that the specified length of data was read */
        read_len = read_binary_block(JPEGFILE, offset, (size_t)length, hdf_buffer);
        VERIFY_VOID(read_len, (size_t)length, "read_binary_block");

        /* Read the block of data from the non-HDF file using nonhdf_offset and
           the length returned by GRgetdatainfo and verify that the specified
           length of data was read */
        read_len = read_binary_block(NONHDF_JPEGFILE, nonhdf_offset, (size_t)length, nonhdf_buffer);
        VERIFY_VOID(read_len, (size_t)length, "read_binary_block");

        /* Compare compressed data from the HDF file against that from the
           non-HDF file.  The two buffers should be identical */
        if (memcmp(hdf_buffer, nonhdf_buffer, (size_t)length)) {
            /* Display any mismatched values for debugging */
            print_mismatched(hdf_buffer, nonhdf_buffer, length);
            num_errs++;
        }

        free(nonhdf_buffer);
        free(hdf_buffer);

        /* Move forward to the next set of non-HDF data, equivalent to the next
           image in the HDF file JPEGFILE */
        nonhdf_offset = nonhdf_offset + length;

        /* Close the image */
        status = GRendaccess(riid);
        CHECK_VOID(status, FAIL, "GRendaccess");
    } /* for n_images */

    /* Terminate access to the GR interface and close the file */
    status = GRend(grid);
    CHECK_VOID(status, FAIL, "GRend");
    status = Hclose(fid);
    CHECK_VOID(status, FAIL, "Hclose");
}

static void
check_im_pal(int32 oldx, int32 oldy, int32 newx, int32 newy, uint8 *oldim, uint8 *newim, uint8 *oldpal,
             uint8 *newpal)
{
    int    error;
    int    x, y;
    uint8 *op, *np;

    MESSAGE(5, printf("Checking image and palette.\n"););

    op = (uint8 *)oldim;
    np = (uint8 *)newim;
    if (newx != oldx || newy != oldy)
        printf("        >>> DIMENSIONS WRONG <<<\n\n");
    error = FALSE;
    for (x = 0; x < oldx; x++)
        for (y = 0; y < oldy; y++) {
            if (*op != *np) {
                printf("\t>>>Error at %d %d, orig image=%d; new image=%d<<<\n", x, y, *op, *np);
                error = TRUE;
            }
            op++;
            np++;
        }
    if (error) {
        printf("    >>> Image is wrong. <<<\n");
        num_errs++;
    }

    error = FALSE;
    for (x = 0; x < 768; x++)
        if (oldpal[x] != newpal[x]) {
            printf("\t>>>Pal error at %d, orig pal %u new pal %u<<<\n", x, oldpal[x], newpal[x]);
            error = TRUE;
        }
    if (error) {
        printf("    >>> Palette is wrong. <<<\n");
        num_errs++;
    }
}

/* ------------------------------- test_r8 -------------------------------- */

#define XD1         10
#define YD1         10
#define XD2         7
#define YD2         11
#define XD3         8
#define YD3         12
#define TESTFILE_R8 "tdfr8.hdf"
void
test_r8(void)
{
    comp_info cinfo; /* compression information for the JPEG */
    uint8    *im3, *ii3;
    uint8    *im2, *ii2;
    uint8    *im1, *ii1;
    uint8    *pal1, *pal2, *ipal;

    int    x, y;
    int    ret, num_images = 0;
    uint16 ref1, ref2;
    int32  xd, yd;
    int    ispal;
    uint8 *jpeg_8bit_temp;

    im1 = (uint8 *)malloc(XD1 * YD1 * sizeof(uint8));
    ii1 = (uint8 *)malloc(XD1 * YD1 * sizeof(uint8));
    if (!im1 || !ii1) {
        fprintf(stderr, "Out of memory!\n");
        exit(1);
    }

    im2 = (uint8 *)malloc(XD2 * YD2 * sizeof(uint8));
    ii2 = (uint8 *)malloc(XD2 * YD2 * sizeof(uint8));
    if (!im2 || !ii2) {
        fprintf(stderr, "Out of memory!\n");
        exit(1);
    }

    im3 = (uint8 *)malloc(XD3 * YD3 * sizeof(uint8));
    ii3 = (uint8 *)malloc(XD3 * YD3 * sizeof(uint8));
    if (!im3 || !ii3) {
        fprintf(stderr, "Out of memory!\n");
        exit(1);
    }

    pal1 = (uint8 *)malloc(768 * sizeof(char));
    pal2 = (uint8 *)malloc(768 * sizeof(char));
    ipal = (uint8 *)malloc(768 * sizeof(char));
    if (!ipal || !pal1 || !pal2) {
        fprintf(stderr, "Out of memory!\n");
        exit(1);
    }

    jpeg_8bit_temp = (uint8 *)malloc(JPEGX * JPEGY);
    if (!jpeg_8bit_temp) {
        fprintf(stderr, "Out of memory!\n");
        exit(1);
    }

    for (y = 0; y < YD1; y++)
        for (x = 0; x < XD1; x++)
            im1[y * XD1 + x] = (uint8)(x + y);
    for (y = 0; y < YD2; y++)
        for (x = 0; x < XD2; x++)
            im2[y * XD2 + x] = (uint8)((2 * x + y) - 256 * ((2 * x + y) / 256));
    for (y = 0; y < YD3; y++)
        for (x = 0; x < XD3; x++)
            im3[y * XD3 + x] = (uint8)((3 * x + y) - 256 * ((3 * x + y) / 256));
    for (x = 0; x < 256; x++) {
        pal1[3 * x]     = (uint8)x;
        pal1[3 * x + 1] = (uint8)x;
        pal1[3 * x + 2] = (uint8)x;
        pal2[x]         = (uint8)x;
        pal2[x + 256]   = (uint8)x;
        pal2[x + 512]   = (uint8)x;
    }

    /* start here */

    MESSAGE(5, printf("Storing 8bit raster images\n"););
    ret = DFR8setpalette(pal1);
    RESULT("DFR8setpalette");

    MESSAGE(5, printf("Putting image with no compression\n"););
    ret = DFR8putimage(TESTFILE_R8, im1, XD1, YD1, 0);
    RESULT("DFR8putimage");
    num_images++;
    ref1 = DFR8lastref();

    MESSAGE(5, printf("Putting image RLE compression\n"););
    ret = DFR8addimage(TESTFILE_R8, im2, XD2, YD2, DFTAG_RLE);
    RESULT("DFR8addimage");
    num_images++;
    ref2 = DFR8lastref();

    ret = DFR8nimages(TESTFILE_R8);
    if (ret != num_images) {
        fprintf(stderr, "        >>> WRONG NUMBER OF IMAGES <<<\n");
        num_errs++;
    }

    MESSAGE(5, printf("Reading and verifying 8bit raster images\n"););

    ret = DFR8restart();
    RESULT("DFR8restart");

    MESSAGE(5, printf("Verifying uncompressed image\n"););

    ret = DFR8getdims(TESTFILE_R8, &xd, &yd, &ispal);
    RESULT("DFR8getdims");
    ret = DFR8getimage(TESTFILE_R8, (uint8 *)ii1, (int32)XD1, (int32)YD1, ipal);
    RESULT("DFR8getimage");
    check_im_pal(XD1, YD1, xd, yd, im1, ii1, pal1, ipal);

    MESSAGE(5, printf("Verifying RLE compressed image\n"););

    ret = DFR8getdims(TESTFILE_R8, &xd, &yd, &ispal);
    RESULT("DFR8getdims");

    MESSAGE(5, printf("Rechecking RLE image\n"););

    ret = DFR8readref(TESTFILE_R8, ref2);
    RESULT("DFR8readref");
    ret = DFR8getimage(TESTFILE_R8, (uint8 *)ii2, (int32)XD2, (int32)YD2, ipal);
    RESULT("DFR8getimage");
    check_im_pal(XD2, YD2, XD2, YD2, im2, ii2, pal1, ipal);

    MESSAGE(5, printf("Changing palette of first image\n"););

    ret = DFR8writeref(TESTFILE_R8, ref1);
    RESULT("DFR8writeref");
    ret = DFR8setpalette(pal2);
    RESULT("DFR8setpalette");
    ret = DFR8addimage(TESTFILE_R8, im1, XD1, YD1, DFTAG_RLE);
    RESULT("DFR8addimage");

    MESSAGE(5, printf("Verifying palette change\n"););

    ret = DFR8readref(TESTFILE_R8, ref1);
    RESULT("DFR8readref");
    ret = DFR8getdims(TESTFILE_R8, &xd, &yd, &ispal);
    RESULT("DFR8getdims");
    ret = DFR8getimage(TESTFILE_R8, (uint8 *)ii1, (int32)XD1, (int32)YD1, ipal);
    RESULT("DFR8getimage");
    check_im_pal(XD1, YD1, xd, yd, im1, ii1, pal2, ipal);

    MESSAGE(5, printf("\nStoring 8-bit images with JPEG compression\n"););

    MESSAGE(6, printf("Storing first image with JPEG quality 80\n"););
    cinfo.jpeg.quality        = 80;
    cinfo.jpeg.force_baseline = TRUE;
    DFR8setcompress(COMP_JPEG, &cinfo);
    ret = DFR8putimage(JPEGFILE, jpeg_8bit_orig, JPEGX, JPEGY, COMP_JPEG);
    RESULT("DFR8putimage");

    MESSAGE(6, printf("Storing second image with JPEG quality 30\n"););
    cinfo.jpeg.quality        = 30;
    cinfo.jpeg.force_baseline = TRUE;
    DFR8setcompress(COMP_JPEG, &cinfo);
    ret = DFR8addimage(JPEGFILE, jpeg_8bit_orig, JPEGX, JPEGY, COMP_JPEG);
    RESULT("DFR8addimage");

    MESSAGE(6, printf("Storing third image with JPEG default quality of 75\n"););
    ret = DFR8addimage(JPEGFILE, jpeg_8bit_orig, JPEGX, JPEGY, COMP_JPEG);
    RESULT("DFR8addimage");

    MESSAGE(5, printf("\nReading and verifying 8-bit JPEG'ed images\n\n"););

    ret = DFR8restart();
    RESULT("DFR8restart");

    ret = DFR8getdims(JPEGFILE, &xd, &yd, &ispal);
    RESULT("DFR8getdims");

    if ((xd != JPEGX) || (yd != JPEGY)) {
        fprintf(stderr, "Returned meta-data is wrong for JPEG quality 80 image\n");
        num_errs++;
    }

    ret = DFR8getimage(JPEGFILE, (uint8 *)jpeg_8bit_temp, JPEGX, JPEGY, NULL);
    RESULT("DFR8getimage");

    if (memcmp(jpeg_8bit_temp, jpeg_8bit_j80, sizeof(jpeg_8bit_orig))) {
        fprintf(stderr, "8-bit JPEG quality 80 image was incorrect\n");
        num_errs++;
    }

    ret = DFR8getdims(JPEGFILE, &xd, &yd, &ispal);
    RESULT("DFR8getdims");

    if ((xd != JPEGX) || (yd != JPEGY)) {
        fprintf(stderr, "Returned meta-data is wrong for JPEG quality 30 image\n");
        num_errs++;
    }

    ret = DFR8getimage(JPEGFILE, (uint8 *)jpeg_8bit_temp, JPEGX, JPEGY, NULL);
    RESULT("DFR8getimage");

    if (memcmp(jpeg_8bit_temp, jpeg_8bit_j30, sizeof(jpeg_8bit_orig))) {
        fprintf(stderr, "8-bit JPEG quality 30 image was incorrect\n");
        num_errs++;
    }

    ret = DFR8getdims(JPEGFILE, &xd, &yd, &ispal);
    RESULT("DFR8getdims");

    if ((xd != JPEGX) || (yd != JPEGY)) {
        fprintf(stderr, "Returned meta-data is wrong for JPEG quality 75 image\n");
        num_errs++;
    }

    ret = DFR8getimage(JPEGFILE, (uint8 *)jpeg_8bit_temp, JPEGX, JPEGY, NULL);
    RESULT("DFR8getimage");

    if (memcmp(jpeg_8bit_temp, jpeg_8bit_j75, sizeof(jpeg_8bit_orig))) {
        fprintf(stderr, "8-bit JPEG quality 75 image was incorrect\n");
        num_errs++;
    }

    free(im1);
    free(ii1);
    free(im2);
    free(ii2);
    free(im3);
    free(ii3);
    free(pal1);
    free(pal2);
    free(ipal);
    free(jpeg_8bit_temp);

    /* Temporarily call to test GRgetcomptype() for hmap project; these tests
       will need to be reformatted. Mar 13, 2011 -BMR */
    test_GRgetcomptype();
}

void
test_pal(void)
{
    int    i;
    int    ret;
    uint16 ref1, ref2;

    uint8 *pal1, *pal2, *ipal;

    pal1 = (uint8 *)malloc(768 * sizeof(uint8));
    pal2 = (uint8 *)malloc(768 * sizeof(uint8));
    ipal = (uint8 *)malloc(768 * sizeof(uint8));
    if (!ipal || !pal1 || !pal2) {
        fprintf(stderr, "Out of memory!\n");
        exit(1);
    }

    for (i = 0; i < 256; i++) {
        pal1[3 * i]     = (uint8)i;
        pal1[3 * i + 1] = (uint8)i;
        pal1[3 * i + 2] = (uint8)i;
        pal2[i]         = (uint8)i;
        pal2[i + 256]   = (uint8)i;
        pal2[i + 512]   = (uint8)i;
    }

    MESSAGE(5, printf("Adding palettes to a file\n"););

    ret = DFPputpal(TESTFILE, pal1, 0, "w");
    RESULT("DFPputpal");
    ref1 = DFPlastref();

    ret = DFPaddpal(TESTFILE, pal2);
    RESULT("DFPaddpal");
    ref2 = DFPlastref();

    MESSAGE(5, printf("Reading and verifying palettes\n"););

    ret = DFPrestart();
    RESULT("DFPrestart");

    /* read and check palette 1 */
    ret = DFPgetpal(TESTFILE, ipal);
    RESULT("DFPgetpal");
    if (memcmp(ipal, pal1, 768) != 0)
        for (i = 0; i < 768; i++)
            if ((uint8)pal1[i] != (uint8)ipal[i])
                printf("Error at %d, ipal %d pal1 %d\n", (int)i, (int)ipal[i], (int)pal1[i]);

    if (ref1 != DFPlastref()) {
        fprintf(stderr, "  >>> DFPlastref() bad for palette 1 <<<\n");
        num_errs++;
    }

    /* read and check palette 2 */
    ret = DFPgetpal(TESTFILE, ipal);
    RESULT("DFPgetpal");
    if (memcmp(ipal, pal2, 768) != 0)
        for (i = 0; i < 768; i++)
            if ((uint8)ipal[i] != (uint8)pal2[i])
                printf("Error at %d, ipal %d pal2 %d\n", (int)i, (int)ipal[i], (int)pal2[i]);

    if (ref2 != DFPlastref()) {
        fprintf(stderr, "  >>> DFPlastref() bad for palette 2 <<<\n");
        num_errs++;
    }

    if (DFPnpals(TESTFILE) != 2) {
        fprintf(stderr, "  >>> DFPnpals() gives wrong number <<<\n");
        num_errs++;
    }

    /* recheck palette number 2 */
    ret = DFPreadref(TESTFILE, ref2);
    RESULT("DFPreadref");
    ret = DFPgetpal(TESTFILE, ipal);
    RESULT("DFPgetpal");
    if (memcmp(ipal, pal2, 768) != 0)
        for (i = 0; i < 768; i++)
            if (ipal[i] != pal2[i])
                printf("Error at %d, ipal %d pal2 %d\n", i, ipal[i], pal2[i]);

    /* recheck palette number 1 */
    ret = DFPreadref(TESTFILE, ref1);
    RESULT("DFPreadref");
    ret = DFPgetpal(TESTFILE, ipal);
    RESULT("DFPgetpal");
    if (memcmp(ipal, pal1, 768) != 0)
        for (i = 0; i < 768; i++)
            if (ipal[i] != pal1[i])
                printf("Error at %d, ipal %d pal1 %d\n", i, ipal[i], pal1[i]);

    MESSAGE(5, printf("Modifying first palette\n"););
    for (i = 0; i < 256; i++)
        pal1[i + 256] = (uint8)(255 - i);
    ret = DFPwriteref(TESTFILE, ref1);
    RESULT("DFPwriteref");

    ret = DFPputpal(TESTFILE, pal1, 1, "a");
    RESULT("DFPputpal");

    ret = DFPreadref(TESTFILE, ref1);
    RESULT("DFPreafref");

    ret = DFPgetpal(TESTFILE, ipal);
    RESULT("DFPgetpal");
    if (memcmp(ipal, pal1, 768) != 0)
        for (i = 0; i < 768; i++)
            if (ipal[i] != pal1[i])
                printf("(%d) Error at %d, ipal %d pal1 %d\n", __LINE__, i, ipal[i], pal1[i]);
    free(pal1);
    free(pal2);
    free(ipal);
}
